package com.ziq.base.extension

import android.content.res.Resources
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*

/**
 * 正常编码中一般只会用到 [dp]/[sp] ;
 * 其中[dp]/[sp] 会根据系统分辨率将输入的dp/sp值转换为对应的px
 */
val Float.dp: Float                 // [xxhdpi](360 -> 1080)
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_DIP,
        this,
        Resources.getSystem().displayMetrics
    )

val Int.dp: Int
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_DIP,
        this.toFloat(),
        Resources.getSystem().displayMetrics
    ).toInt()

val Float.sp: Float                 // [xxhdpi](360 -> 1080)
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics
    )

val Int.sp: Int
    get() = android.util.TypedValue.applyDimension(
        android.util.TypedValue.COMPLEX_UNIT_SP,
        this.toFloat(),
        Resources.getSystem().displayMetrics
    ).toInt()

/**
 * 增加try-catch，放弃catch处理
 */
inline fun safeInvoke(
    whenCatch: (e: Exception) -> Unit = {},
    whenFinally: () -> Unit = {},
    whenTry: () -> Unit
) {
    try {
        whenTry.invoke()
    } catch (e: Exception) {//ignore
        whenCatch.invoke(e)
    } finally {
        whenFinally.invoke()
    }
}


fun Any.launchWithTryAsyncGlobal(
    whenTry: suspend () -> Unit,
    whenCatch: suspend (Exception) -> Unit = {
        withContext(Dispatchers.Main){
        }
    },
    whenFinally: suspend () -> Unit = {}
) {
    GlobalScope.launch(Dispatchers.Default) {
        try {
            whenTry()
        } catch (e: Exception) {
            whenCatch(e)
        } finally {
            whenFinally()
        }
    }
}

fun ViewModel.launchWithTry(
    whenTry: suspend () -> Unit,
    whenCatch: suspend (Exception) -> Unit = {it.printStackTrace()},
    whenFinally: suspend () -> Unit = {}
) {
    viewModelScope.launch {
        try {
            whenTry()
        } catch (e: Exception) {
            whenCatch(e)
        } finally {
            whenFinally()
        }
    }
}

fun ViewModel.launchWithTryAsynchronous(
    whenTry: suspend () -> Unit ,
    whenCatch: suspend (Exception) -> Unit = {it.printStackTrace()},
    whenFinally: suspend () -> Unit = {}
) {
    viewModelScope.launch(Dispatchers.Default) {
        try {
            whenTry()
        } catch (e: Exception) {
            whenCatch(e)
        } finally {
            whenFinally()
        }
    }
}

fun LifecycleOwner.launchWithTry(
    whenTry: suspend CoroutineScope.() -> Unit,
    whenCatch: suspend (Exception) -> Unit = {},
    whenFinally: suspend () -> Unit = {}
) {
    lifecycleScope.launch {
        try {
            whenTry.invoke(this)
        } catch (e: Exception) {
            whenCatch(e)
        } finally {
            whenFinally()
        }
    }
}

fun LifecycleOwner.launchWithTryAsynchronous(
    whenTry: suspend () -> Unit,
    whenCatch: suspend (Exception) -> Unit = {},
    whenFinally: suspend () -> Unit = {}
) {
    lifecycleScope.launch(Dispatchers.Default) {
        try {
            whenTry()
        } catch (e: Exception) {
            whenCatch(e)
        } finally {
            whenFinally()
        }
    }
}

